elasticsearch 路由分片

前言

elasticsearch 是一个集分布式存储 + 分布式搜索的引擎,分布式搜索是基于Lucene实现的;其存储天然支持数据的路由分片水平扩展的方式,满足海量数据的水平弹性伸缩,同时支持数据多副本的形式,数据冗余,副本类似于mysql中的从库,对读请求起到负载均衡的作用。从而满足大型互联网架构中的高可用,弹性伸缩,水平扩容以及高并发等特性。

分片规则

当索引一个文档的时候,文档会被存储到一个主分片中。 Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 1 还是分片 2 中呢?

首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。实际上,这个过程是根据下面这个公式决定的:

shard = hash(routing) % number_of_primary_shards

routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到 余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。

这就解释了为什么我们要在创建索引的时候就确定好主分片的数量 并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。

所有的文档 API( get 、 index 、 delete 、 bulk 、 update 以及 mget )都接受一个叫做 routing 的路由参数 ,通过这个参数我们可以自定义文档到分片的映射。一个自定义的路由参数可以用来确保所有相关的文档——例如所有属于同一个用户的文档——都被存储到同一个分片中。

索引文档

image

索引文档的步骤:

  1. 客户端向Node-1发送索引文档请求;
  2. 节点使用文档的_id确定文档属于分片2 。请求会被转发到Node-3,因为分片2 的主分片被分配在Node-3上;
  3. Node-3在主分片上执行请求。如果成功了,它将请求并行转发到所有节点的副本分片上(这里仅Node-2)。一旦所有的副本分片都报告成功, Node-3将向协调节点(Node-1)报告成功,协调节点向客户端报告成功。

在客户端收到成功响应时,文档变更已经在主分片和所有副本分片执行完成,变更是安全的。

检索文档

可以从主分片或者从其它任意副本分片检索文档。

image

检索文档的步骤:

  1. 客户端向Node-1发送检索文档请求;
  2. 节点使用文档的 _id 来确定文档属于分片2 。分片2的副本分片R2存在节点Node-2上。 基于负载均衡将请求转发到Node-2。
  3. Node-2将文档返回给协调节点Node-1,协调节点再将文档返回给客户端;

在处理读取请求时,协调结点在每次请求的时候都会通过轮询主分片或者其它任意副本分片来达到负载均衡。

参考链接

  1. https://www.elastic.co/guide/cn/elasticsearch/guide/current/routing-value.html
  2. https://www.elastic.co/guide/cn/elasticsearch/guide/current/how-primary-and-replica-shards-interact.html
  3. https://www.elastic.co/guide/cn/elasticsearch/guide/current/distrib-read.html
  4. https://www.elastic.co/guide/cn/elasticsearch/guide/current/_partial_updates_to_a_document.html
  5. https://www.elastic.co/guide/cn/elasticsearch/guide/current/distrib-write.html